package com.wanho.java159.cb.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wanho.java159.cb.mapper.CarInfoMapper;
import com.wanho.java159.cb.po.CarInfo;
import com.wanho.java159.cb.po.CarInfoExample;
import com.wanho.java159.cb.repositories.CarInfoRepository;
import com.wanho.java159.common.util.IDUtil;
import com.wanho.java159.common.util.OSSUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* CarInfo 业务处理类
* @author ChaoFei.Zhang
* @date   2021-07-10
*/
@Service
@Transactional
public class CarInfoService {
    /**CarInfo数据访问层对象*/
    @Resource
    private CarInfoMapper carInfoMapper ;

    @Resource
    private IDUtil idUtil ;

    @Resource
    private OSSUtil ossUtil ;

    @Resource
    private ElasticsearchTemplate elasticsearchTemplate ;

    @Resource
    private CarInfoRepository carInfoRepository ;

    /**
    * 查询所有 CarInfo 状态为未删除 is_deleted=0 的数据
    * @return CarInfo所有的数据
    */
    public List<CarInfo> list(){
        CarInfoExample carInfoExample = new CarInfoExample();
        //查询 数据表中 is_deleted = 0
        carInfoExample.createCriteria().andIsDeletedEqualTo(false) ;
        return carInfoMapper.selectByExample(carInfoExample) ;
    }

    /**
    * 根据删除主键删除 CarInfo 逻辑删除 进行is_deleted=1的修改操作
    * @param id CarInfo的主键
    * @return true 删除成功  false 删除失败
    */
    public boolean remove(Long id){
        CarInfo carInfo = new CarInfo();
        carInfo.setId(id);
        carInfo.setIsDeleted(true);
        return carInfoMapper.updateByPrimaryKeySelective(carInfo) > 0 ;
    }

    /**
    * 新增一条CarInfo记录
    * @param  carInfo 封装新增的数据
    * @return true 新增成功  false 新增失败
    */
    public boolean save(CarInfo carInfo){
        carInfo.setId(idUtil.nextId());
        carInfo.setCreateTime(new Date());
        carInfo.setUpdateTime(new Date());
        carInfo.setIsDeleted(false);
        return carInfoMapper.insert(carInfo)>0 ;
    }

    /**
    * 根据主键查询 CarInfo
    * @param id CarInfo的主键
    * @return null id不存在  返回CarInfo对象
    */
    public CarInfo get(Long id){
        //从 es 库中进行查询
        Optional<CarInfo> optional = carInfoRepository.findById(id);
        if (optional.isPresent()){
            return optional.get() ;
        }
        return null ;
    }
    /*public CarInfo get(Long id){
        return carInfoMapper.selectByPrimaryKey(id) ;
    }*/

    /**
    * 修改一条CarInfo记录
    * @param  carInfo 封装修改的数据
    * @return true 修改成功  false 修改失败
    */
    public boolean update(CarInfo carInfo) {
        carInfo.setUpdateTime(new Date());
        return carInfoMapper.updateByPrimaryKeySelective(carInfo)>0 ;
    }

    /**
    * 分页查询 CarInfo  如果有查询条件需要动态在方法体内添加条件
    * @param pageNum 页码
    * @param pageSize 分页跨度
    * @param keyword 封装查询的数据
    * @return 分页对象
    */
    public PageInfo<CarInfo> listPage(Long pageNum, Long pageSize,String keyword) {
        Pageable pageable = PageRequest.of(pageNum.intValue() - 1, pageSize.intValue()) ;
        //关键字为空  查询返回所有
        if (StringUtils.isEmpty(keyword)){
            Page<CarInfo> carInfoPage = carInfoRepository.findAll(pageable);
            return this.page2PageInfo(carInfoPage) ;
        }
        ConvertUtils.register(new Converter() {
            @Override
            public Object convert(Class clazz, Object value) {
                //将String转化为date
                SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
                Date parse=null;
                try {
//parse()返回的是一个Date类型数据，format返回的是一个StringBuffer类型的数据
                    parse =format.parse(value.toString());
                } catch (ParseException e) {

                    e.printStackTrace();
                }
                return parse;
            }
        }, Date.class);
        //创建一个查询对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.queryStringQuery(keyword).defaultField("carMaster"))
                .withHighlightFields(new HighlightBuilder.Field("carMaster").preTags("<font color='red'>").postTags("</font>"))
                .withPageable(PageRequest.of(0, 15))
                .build();
        //执行查询
        Page<CarInfo> carInfoPage = elasticsearchTemplate.queryForPage(query, CarInfo.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<CarInfo> imageTemp = new ArrayList<>();
                SearchHits hits = searchResponse.getHits();
                try {
                    for (SearchHit searchHit : hits) {
                        Map<String, Object> documentMap = searchHit.getSource();
                        CarInfo carInfo = new CarInfo();
                        BeanUtils.populate(carInfo, documentMap);
                        Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                        //取title高亮显示的结果
                        HighlightField field = highlightFields.get("carMaster");
                        Text[] fragments = field.getFragments();
                        if (fragments != null) {
                            String productname = fragments[0].toString();
                            BeanUtils.setProperty(carInfo, "carMaster", productname);
                        }
                        imageTemp.add(carInfo) ;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return new AggregatedPageImpl<>((List<T>) imageTemp);
            }
        });
        return this.page2PageInfo(carInfoPage) ;
    }

    /**
     *  spring data Page 转成 pageHelper 的pageinfo 对象
     *  保证：前端项目的无需修改，api接口文档不做修改
     * @param carInfoPage
     * @return
     */
    private PageInfo<CarInfo> page2PageInfo(Page<CarInfo> carInfoPage){
        PageInfo<CarInfo> carInfoPageInfo = new PageInfo<>();
        carInfoPageInfo.setList(carInfoPage.getContent());
        carInfoPageInfo.setTotal(carInfoPage.getTotalElements());
        carInfoPageInfo.setPages(carInfoPage.getTotalPages());
        return carInfoPageInfo ;
    }
    /*public PageInfo<CarInfo> listPage(Long pageNum, Long pageSize,CarInfo carInfo) {
        String s = carInfo.getCarNo();
        PageHelper.startPage(pageNum.intValue(),pageSize.intValue());
        CarInfoExample carInfoExample = new CarInfoExample();
        CarInfoExample.Criteria criteria = carInfoExample.createCriteria();
        criteria.andIsDeletedEqualTo(false);
        //根据车辆VIN 模糊查询
        if (StringUtils.isNotEmpty(carInfo.getVin())){
            criteria.andVinLike("%"+carInfo.getVin()+"%") ;
        }
        //根据车牌号 模糊查询
        if (StringUtils.isNotEmpty(carInfo.getCarNo())){
            criteria.andCarNoLike("%"+s+"%") ;
        }
        return new PageInfo<>(carInfoMapper.selectByExample(carInfoExample));
    }*/


    /**
     * 上传图片到 OSS
     * @param multipartFile
     * @return
     */
    public String uploadPic(MultipartFile multipartFile){
        try{
            String originalFilename = multipartFile.getOriginalFilename();
            //获得文件后缀
            String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
            //获得图片名
            String fileName = UUID.randomUUID().toString()+extendsName ;
            InputStream inputStream = multipartFile.getInputStream();
            String picLocation = ossUtil.putImage2OSS(fileName, inputStream);
            return  picLocation ;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("文件上传错误！！") ;
        }
    }
}
